<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="../css/style.css" type="text/css" media="screen">
</head>
<body>
    <div class="entry"> 
 <div id="toc">
  <strong>目录</strong>
  <span>[hide]</span> 
  <ul id="toc_l"> 
   <li><a href="#Program Run">程序运行</a></li> 
   <li><a href="#Imported_functions_call">导入函数调用 </a></li> 
  </ul> 
 </div> 
 <p>想让MQL4程序运行起来，就必须对它进行编译(按“编译”按钮或F5键)。在程序编译过程中不允许出现任何错误(允许有警告信息，但一定要对它进行具体分析)。编译成功之后，将会在相应的目录<em><strong>terminal_dir\experts，</strong></em><em><strong>terminal_dir\experts\indicators</strong>，</em>或 <em><strong>terminal_dir\experts\scripts</strong> </em>中，自动创建一个扩展名为<strong><em>.EX4</em></strong>的可执行文件，只有创建了相应的<strong><em>.EX4</em></strong>文件，MQL4程序(EA，脚本，自定义指标)才能够被用户运行起来。</p> 
 <p>用户通过鼠标可以将智能交易、自定义指标和脚本从客户端“导航”窗口拖动到相应的图表上(拖曳技术)，它们会附加到已打开的任一图表上。MQL4程序只有在客户端已启动的基础上才能运行。</p> 
 <p>要停止智能交易运行，必须从图表的上下文菜单中删除它(智能交易系统-取消)。“启用智能交易”按钮状态将会直接影响智能交易的运行。</p> 
 <p>要使自定义指标停止运行，应该将它从图表中删除。</p> 
 <p>自定义指标和智能交易一直运行着，直到用户从图表中明确地删除它们为止。有关附加的智能交易和自定义指标的信息在客户端启动之时保存于客户端内。</p> 
 <p>在脚本己经完成操作之后、当前图表被关闭或其状态己经发生改变、或当客户端中断运行时，脚本都只执行一次任务，并被自动删除掉。由于不保存运行状态信息，当客户端再次重新启动时脚本并不自动运行。</p> 
 <p>在同一个图表内，智能交易、脚本和更多数量的指标可以同时运行。</p> 
 <div class="divider top-of-page">
  <a title="Top of Page" href="#top">Back to Top</a>
 </div> 
 <h2><a name="Program Run"></a>程序运行</h2> 
 <p>程序附加到图表之后，它立即开始与init()函数协同运行。在客户端开始运行和历史数据(仅与智能交易有关，而与指标无关)被另外加载之后、当货币对和图表时段改变了、在MetaEditor里重新编译之后、或者从智能交易或自定义指标的设置窗口改变了输入参数，附加到图表上的智能交易和自定义指标中的init()函数将会运行。当计算结果发生变化时，智能交易同样也会被初始化。</p> 
 <p>每一个附加到图表上的程序可以借助deinit()函数完成善后工作。当客户端关机、图表被关闭、在货币对或图表时段改变之前、程序重编译成功、改变了输入参数或计算结果改变了，deinit()函数都会运行。在deinit()函数执行期间，用户可以使用<a href="386.html#UninitializeReason">UninitializeReason()函数</a>查看未初始化成功的原因。</p> 
 <p>deinit()函数必须在2.5秒内执行完毕，如果函数在这段时问内没有完成它的工作，它将会被强制结束。脚本是这一条规则的例外，由于它们能正常地自主完成它们的工作，它的运行不取决于任何外界的命令。如果一个脚本工作时间过长(例如，永无止境的死循环)，用户可以应用外部命令结束它的运行(从图表的上下文菜单中删除脚本、在原有的图表上添加新的脚本、改变图表的货币对或时段)。 在这种情况下，deinit()函数同样被限制在2.5秒内。</p> 
 <p>在收到新报价时，智能交易和自定义指标中start()函数将会被执行。当新报价进入时，如果start()函数还在忙着处理前面的报价，智能交易会忽略新报价而不予处理。在start()函数运行期间，所有新收的报价都会被一跳而过，直到当前start()函数运行完成为止。从那之后，仅在收到源源不断的新报价时，start()函数才一会运行。对于自定义的指标，由于收到了新报价，当前图表货币对或时段发生了变化，start()函数将会重新运行。start()函数是否运行还取决于“启用/禁用智能交易”按钮状态，当“启用/禁用智能交易”按钮处于禁用状态时，start()函数不会运行，但是，当通过该按钮切换到禁用状态时，不会中断当前start()函数运行。在智能交易属性窗口打开时，start()函数将停止运行，在其执行期间也不会被打开。</p> 
 <p>从图表中卸载程序、改变货币对或图表时段、计算结果发生了变化、关闭图表、客户端关机，都将会中断程序的执行。如果这些中断程序执行的指令到来的时候，start()函数此刻还在运行，那留给它的工作时间依然被限制在2.5秒之内。程序知道用内置<a href="386.html#IsStopped">IsStopped()函数</a>试着把它关闭并正确地结束它的工作。</p> 
 <p>脚本的执行不依赖收到的报价。在货币对或图表时段发生改变时，脚本将完成它的工作并从客户端上卸载下来。</p> 
 <p>脚本和智能交易运行在自己的线程里，自定义指标则工作在主接口线程上。但是，如果一个自定义指标被<a href="406.html#iCustom">iCustom()函数</a>调用，这个指标就运行在调用它的程序线程中，库(导入)函数也同样工作在调用程序的线程里。</p> 
 <div class="divider top-of-page">
  <a title="Top of Page" href="#top">Back to Top</a>
 </div> 
 <h2><a name="Imported_functions_call"></a>导入函数调用</h2> 
 <p>为了在mql4程序执行期间<a href="373.html#Importing_of_functions">导入函数</a>，采用了所谓的“滞后联编”。这就意味着，导入函数被调用前，不会被加载相应的模块(EX4或DLL)。 MQL4和DLL库在调用模块线程下运行。</p> 
 <p>这里不推荐使用全路径模块名 Drive:\Directory\FileName.Ext 加载模块。MQL4库是从 terminal_dir\experts\libraries 文件夹中载入进来。如果库中未找到，将会尝试从terminal_dir\experts 文件夹下加载。</p> 
 <p>系统动态链接库(DLL)按照操作系统规则加载。如果一个DLL已经加载过(例如，被其他智能交易系统，或从同时启动的另一个客户端程序加载)，则将直接引用已加载过的库，否则，搜索会按照以下顺序进行:</p> 
 <ul> 
  <li>1. <em>terminal_dir\experts\libraries </em>目录 。</li> 
  <li>2. <em>terminal_dir </em>目录，客户端程序启动的目录。</li> 
  <li>3. 当前目录。</li> 
  <li>4. <em>windows_dir\SYSTEM32</em> 系统目录 (或是Win98下 <em>windows_dir\SYSTEM</em> 目录 )。</li> 
  <li>5. <em>windows_dir </em>目录，即操作系统安装的目录。</li> 
  <li>6. 系统环境变量PATH中列出的目录。</li> 
 </ul> 
 <p>如果一个DLL运行时调用了另一个DLL，而后者又不可用，那么前者就不会被加载。</p> 
 <p>与系统库不同，自定义库(MQL4)是每个调用模块各自单独加载，而不管是否被其它模块独立地加载过。例如，调用.ex4模块可以从lib1.ex4和lib2.ex4库中调用函数，反过来，lib1.ex4库也可以从lib2.ex4库中调用函数。在这种情况下，一个以上lib1.ex4副本和两份lib2.ex4副本被加载，根本不考虑所有的调用都来自同一个调用.ex4模块。</p> 
 <p>从DLL导入到MQL4程序的函数必须符合Windows API函数的链接规则。为了确保在程序源码里符合这样的规定，我们用C或C++语言编程时使用关键字_stdcall予以说明，表示是用微软公司编译器编译。上述链接规定有以下特点:</p> 
 <ul> 
  <li>为了将函数参数以适当的方式置入堆栈，调用函数(这种情况下，是一个MQL4程序)必须“看得见”被调用函数的原型(来自DLL导入函数)；</li> 
  <li>调用函数(这种情况下，是一个MQL4程序)以逆序方式将参数置入堆栈，也就是说，从右到左；它就是以这种顺序让导入函数读取传递给它的参数；</li> 
  <li>参数通过值传递，除那些明确说明通过引用传递之外；</li> 
  <li>在读取传递给它的参数后，导入函数本身将会自行清除堆栈。</li> 
 </ul> 
 <p>在描述导入函数原型时，由于所有的参数必须明确地传递给导入函数，所以参数的默认值是无用的。</p> 
 <p>如果调用导入函数失败(智能交易设置不允许DLL导入，或是由于一些原因导致无法加载相应的库)，智能交易会停止运行并把相关信息输出到“智能交易停止”日志。另外，智能交易只有在重新初始化之后才能启动。重新编译或打开智能交易属性表并按OK键，其结果就是智能交易系统重新初始化。</p> 
 <div class="divider top-of-page">
  <a title="Top of Page" href="#top">Back to Top</a>
 </div> 本文地址：
 <a href="380.html" rel="bookmark"><b>380.html</b></a> 
</div>
</body>
</html>